# -*- coding: utf-8 -*-

from game.models import *

# Funciones útiles para la comunicación Servidor -> Cliente

class GamesMixin(object):

    def __init__(self, *args, **kwargs):
        super(GamesMixin, self).__init__(*args, **kwargs)
        if 'games' not in self.session:
            self.session['games'] = set()  # a set of simple strings


    def join(self, game):
        """Lets a user join a room on a specific Namespace."""
        self.session['games'].add(self._get_game_name(game))


    def leave(self, game):
        """Lets a user leave a room on a specific Namespace."""
        self.session['games'].remove(self._get_game_name(game))


    def _get_game_name(self, game):
        return unicode(self.ns_name) + u'_' + unicode(game)


    def emit_to_game(self, game, event, *args):
        """This is sent to all in the game (in this particular Namespace)"""
        pkt = dict(type="event",
                   name=event,
                   args=args,
                   endpoint=self.ns_name)
        game_name = self._get_game_name(game)
        for sessid, socket in self.socket.server.sockets.iteritems():
            if 'games' not in socket.session:
                continue
            if game_name in socket.session['games']:
                socket.send_packet(pkt)


    def emit_to_player(self, event, *args):
        """This is sent to the player himself"""
        pkt = dict(type="event",
                    name=event,
                    args=args, 
                    endpoint=self.ns_name)
        self.socket.send_packet(pkt)


    def emit_to_other_player(self, player, event, *args):
        """This is sent to the other player (player)"""
        
        pkt = dict(type="event",
                    name=event,
                    args=args, 
                    endpoint=self.ns_name)

        socket_destination = self.socket.server.sockets.get(player.session_id)
        socket_destination.send_packet(pkt)


    # Actualización de base (recursos, ejército)
    def emit_base_to_player(self, base):
        speed_bonus = False
        if base.bonus == 'S':
            speed_bonus = True
        self.emit_to_player('bases', base.id, base.x_coordinate,
                            base.y_coordinate, base.resources, base.get_ants(),
                            speed_bonus)


    # Actualización de base (recursos, ejército) de un jugador indicado
    def emit_base_to_other_player(self, base):
        speed_bonus = False
        if base.bonus == 'S':
            speed_bonus = True
        self.emit_to_other_player(base.player, 'bases', base.id,
                                    base.x_coordinate, base.y_coordinate,
                                    base.resources, base.get_ants(),
                                    speed_bonus)


    
    # Actualización de bases propias de un jugador (recursos, ejército)
    def emit_bases_to_player(self, player):
        """
        """
        bases_ids, x_coordinates, y_coordinates, resources, ants = [], [], [], [], []
        speed_bonus = False
        for base in player.bases.all():
            bases_ids.append(base.id)
            x_coordinates.append(base.x_coordinate)
            y_coordinates.append(base.y_coordinate)
            resources.append(base.resources)
            ants.append(base.get_ants())
            if base.bonus == 'S':
                speed_bonus = True
            
        self.emit_to_player('bases', bases_ids, x_coordinates, y_coordinates,
                            resources, ants, speed_bonus)


    # Actualización de bases propias de un jugador (recursos, ejército)
    def emit_bases_to_other_player(self, player):
    
        bases_ids, x_coordinates, y_coordinates, resources, ants = [], [], [], [], []
        speed_bonus = False
        for base in player.bases.all():
            bases_ids.append(base.id)
            x_coordinates.append(base.x_coordinate)
            y_coordinates.append(base.y_coordinate)
            resources.append(base.resources)
            ants.append(base.get_ants())
            if base.bonus == 'S':
                speed_bonus = True
        self.emit_to_other_player(player, 'bases', bases_ids, x_coordinates,
                                    y_coordinates, resources, ants, speed_bonus)


    # Actualiza la información de estadísticas de la partida
    def emit_players_statistics_to_game(self, game):
    
        players_growth_points, players_names, players_ids, players_kill_points, players_roles = [], [], [], [], []
        for player in Player.objects.filter(game=game):
            players_ids.append(player.id)
            players_growth_points.append(player.get_growth_statistics())
            players_kill_points.append(player.kill_points)
            players_names.append(player.name)
            players_roles.append(player.get_bonus_display())
            
        self.emit_to_game(game.id, 'players', players_ids, players_names, players_growth_points, players_kill_points, players_roles)


    # Actualización de "mapa"
    def emit_map_to_game(self, game, player_id=None, speed_bonus=False):

        players_id, players_name, x_coordinates, y_coordinates, bases_ids, levels, bonus, resources_limit, players_roles, players_growth_points, players_kill_points = [], [], [], [], [], [], [], [], [], [], []
        for base in Base.objects.filter(game=game):
            bases_ids.append(base.id)
            x_coordinates.append(base.x_coordinate)
            y_coordinates.append(base.y_coordinate)
            levels.append(base.level)
            resources_limit.append(int(base.resources_limit))

            if base.bonus:
                bonus.append(base.get_bonus_display())
            else:
                bonus.append(None)

            if base.player:
                players_id.append(base.player.id)
                players_name.append(base.player.name)
                players_roles.append(base.player.get_bonus_display())
                players_growth_points.append(base.player.get_growth_statistics())
                players_kill_points.append(base.player.kill_points)
            else:
                players_id.append(None)
                players_name.append(None)
                players_roles.append(None)
                players_growth_points.append(None)
                players_kill_points.append(None)

        self.emit_to_game(game.id, 'map', bases_ids, x_coordinates, y_coordinates, players_id, players_name, players_roles, players_growth_points, players_kill_points, player_id, speed_bonus, levels, bonus, resources_limit)




    # EVENTS



    def emit_event_uphold_to_player(self, uphold, type_event, list_ants):
        
        if uphold.base_start.player:
            playername_start = unicode(uphold.base_start.player.name)
        else:
            playername_start = None

        if uphold.base_finish.player:
            playername_finish = unicode(uphold.base_finish.player.name)
        else:
            playername_finish = None
        
        self.emit_to_player('time_event_uphold', uphold.id, type_event,
            uphold.seconds, uphold.base_start.id,
            uphold.base_start.x_coordinate, uphold.base_start.y_coordinate,
            playername_start, uphold.base_finish.id,
            uphold.base_finish.x_coordinate, uphold.base_finish.y_coordinate,
            playername_finish, None, list_ants)



    def emit_event_movement_to_player(self, movement, type_event, num_workers,
                                        resources):
        """
            Envía evento de movimiento de recursos a un jugador determinado
        """

        if movement.base_start.player:
            playername_start = unicode(movement.base_start.player.name)
        else:
            playername_start = None

        if movement.base_finish.player:
            playername_finish = unicode(movement.base_finish.player.name)
        else:
            playername_finish = None
            
        self.emit_to_player('time_event_resources', movement.id, type_event,
                            movement.seconds, movement.base_start.id,
                            movement.base_start.x_coordinate,
                            movement.base_start.y_coordinate,
                            playername_start, movement.base_finish.id,
                            movement.base_finish.x_coordinate,
                            movement.base_finish.y_coordinate,
                            playername_finish, num_workers, resources)



    def emit_event_attack_to_player(self, attack, type_event, list_ants=None,
                                    stolen_resources=None, seconds=None):
        """
            Emite evento de ataque al jugador que provoca la llamada
        """

        if seconds is None:
            seconds = attack.seconds

        if attack.base_finish.player:
            playername_finish = unicode(attack.base_finish.player.name)
        else:
            playername_finish = None

        if attack.base_start.player:
            playername_start = unicode(attack.base_start.player.name)
        else:
            playername_start = None

        self.emit_to_player('time_event_attack', attack.id, type_event,
                            seconds, attack.base_start.id,
                            attack.base_start.x_coordinate, 
                            attack.base_start.y_coordinate,
                            playername_start, attack.base_finish.id,
                            attack.base_finish.x_coordinate,
                            attack.base_finish.y_coordinate,
                            playername_finish,
                            stolen_resources, list_ants)



    def emit_event_attack_to_other_player(self, player, attack, type_event,
                                    list_ants=None, stolen_resources=None, 
                                    seconds=None):
        """
            Emite evento de ataque a un jugador determinado
        """

        if seconds is None:
            seconds = attack.seconds

        if attack.base_finish.player:
            playername_finish = unicode(attack.base_finish.player.name)
        else:
            playername_finish = None

        if attack.base_start.player:
            playername_start = unicode(attack.base_start.player.name)
        else:
            playername_start = None

        self.emit_to_player(player, 'time_event_attack', attack.id, type_event,
                            attack.seconds, attack.base_start.id,
                            attack.base_start.x_coordinate, 
                            attack.base_start.y_coordinate,
                            playername_start, attack.base_finish.id,
                            attack.base_finish.x_coordinate,
                            attack.base_finish.y_coordinate,
                            playername_finish, stolen_resources, list_ants)



    # REPORTS



    def emit_uphold_report_to_player(self, uphold):
        self.emit_to_player('uphold_report', uphold.uphold_report.id,
            uphold.base_start.game.date_created.strftime('%d/%m/%Y %H:%M:%S'),
            uphold.uphold_report.date_created.strftime('%d/%m/%Y %H:%M:%S'),
            uphold.uphold_report.name_start, uphold.base_start.x_coordinate,
            uphold.base_start.y_coordinate, uphold.uphold_report.name_finish,
            uphold.base_finish.x_coordinate, uphold.base_finish.y_coordinate,
            uphold.uphold_report.get_ants_uphold_init_list(),
            uphold.uphold_report.get_ants_uphold_finish_list(),
            uphold.uphold_report.info)

    def emit_movement_report_to_player(self, movement):
    
        self.emit_to_player('movement_report',
            movement.movement_report.id,
            movement.base_start.game.date_created.strftime('%d/%m/%Y %H:%M:%S'),
            movement.movement_report.date_created.strftime('%d/%m/%Y %H:%M:%S'),
            movement.movement_report.name_start,
            movement.base_start.x_coordinate,
            movement.base_start.y_coordinate,
            #movement.movement_report.base_start.x_coordinate,
            #movement.movement_report.base_start.y_coordinate,
            movement.movement_report.name_finish,
            movement.base_finish.x_coordinate,
            movement.base_finish.y_coordinate,
            #movement.movement_report.base_finish.x_coordinate,
            #movement.movement_report.base_finish.y_coordinate,
            movement.movement_report.info)



    def emit_battle_report_to_player(self, attack, invisible=False):
        self.emit_to_player('battle_report', attack.battle_report.id,
            attack.base_start.game.date_created.strftime('%d/%m/%Y %H:%M:%S'),
            attack.battle_report.date_created.strftime('%d/%m/%Y %H:%M:%S'),
            attack.battle_report.name_start,
            attack.base_start.x_coordinate,
            attack.base_start.y_coordinate,
            #attack.battle_report.base_start.x_coordinate,
            #attack.battle_report.base_start.y_coordinate,
            attack.battle_report.get_ants_attack_start_list(),
            attack.battle_report.get_ants_attack_finish_list(),
            attack.battle_report.get_ants_attack_deads_list(),
            attack.battle_report.name_finish,
            attack.base_finish.x_coordinate,
            attack.base_finish.y_coordinate,
            #attack.battle_report.base_finish.x_coordinate, 
            #attack.battle_report.base_finish.y_coordinate,
            attack.battle_report.get_ants_defend_start_list(invisible),
            attack.battle_report.get_ants_defend_finish_list(invisible),
            attack.battle_report.get_ants_defend_deads_list(invisible),
            attack.battle_report.info)



    def emit_battle_report_to_other_player(self, player, attack, invisible=False):
        self.emit_to_other_player(player_finish, 'battle_report',
            attack.battle_report.id,
            attack.base_start.game.date_created.strftime('%d/%m/%Y %H:%M:%S'),
            attack.battle_report.date_created.strftime('%d/%m/%Y %H:%M:%S'),
            attack.battle_report.name_start,
            attack.base_start.x_coordinate,
            attack.base_start.y_coordinate,
            #attack.battle_report.base_start.x_coordinate,
            #attack.battle_report.base_start.y_coordinate,
            attack.battle_report.get_ants_attack_start_list(),
            attack.battle_report.get_ants_attack_finish_list(),
            attack.battle_report.get_ants_attack_deads_list(),
            attack.battle_report.name_finish,
            attack.base_finish.x_coordinate,
            attack.base_finish.y_coordinate,
            #attack.battle_report.base_finish.x_coordinate,
            #attack.battle_report.base_finish.y_coordinate,
            attack.battle_report.get_ants_defend_start_list(invisible),
            attack.battle_report.get_ants_defend_finish_list(invisible),
            attack.battle_report.get_ants_defend_deads_list(invisible),
            attack.battle_report.info)



